package com.hanqian.kepler.core.service.core.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.hanqian.kepler.common.bean.result.AjaxResult;
import com.hanqian.kepler.common.enums.BaseEnumManager;
import com.hanqian.kepler.common.enums.DictEnum;
import com.hanqian.kepler.common.jpa.specification.OP;
import com.hanqian.kepler.common.jpa.specification.Rule;
import com.hanqian.kepler.common.jpa.specification.SpecificationFactory;
import com.hanqian.kepler.common.utils.StringUtils;
import com.hanqian.kepler.core.dao.primary.core.TargetDao;
import com.hanqian.kepler.core.entity.primary.core.Target;
import com.hanqian.kepler.core.entity.primary.sys.Dict;
import com.hanqian.kepler.core.service.core.TargetService;
import com.hanqian.kepler.core.service.flow.BaseFlowService;
import com.hanqian.kepler.core.service.flow.impl.BaseFlowServiceImpl;
import com.hanqian.kepler.core.service.sys.DictService;
import com.hanqian.kepler.flow.base.dao.BaseFlowDao;
import com.hanqian.kepler.flow.enums.FlowEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * newFile
 * ============================================================================
 * author : dzw
 * createDate:  2020/12/21 。
 * ============================================================================
 */
@Slf4j
@Service
public class TargetServiceImpl extends BaseFlowServiceImpl<Target> implements TargetService {

	@Autowired
	private TargetDao targetDao;
	@Autowired
	private DictService dictService;

	@Override
	public BaseFlowDao<Target> getBaseFlowDao() {
		return targetDao;
	}

	@Override
	public String getNewTargetNo(Date date) {
		if(date == null) date = new Date();
		String year = DateUtil.format(date, "yyyy");
		String month = DateUtil.format(date, "MM");

		List<Rule> rules = new ArrayList<>();
		rules.add(Rule.notNull("processState"));
		rules.add(Rule.ne("processState", FlowEnum.ProcessState.Draft));
		rules.add(Rule.eq("year", year));
		rules.add(Rule.eq("month", month));
		long count = count(SpecificationFactory.where(rules)) + 1;
		return year + month + StringUtils.autoNo(3, Convert.toInt(count));
	}

	@Override
	public String getNamesByIds(String ids) {
		List<String> nameList = new ArrayList<>();
		ListUtil.of(StrUtil.split(ids, ",")).forEach(id -> {
			Target target = get(id);
			if(target != null) nameList.add(target.getName());
		});
		return StrUtil.join(",", nameList);
	}

	@Override
	public void updateRelatedTarget(Target target, String newRelatedTargetIds) {
		if(target == null || ObjectUtil.equal(FlowEnum.ProcessState.Draft, target.getProcessState())) return;

		String keyId = target.getId();
		List<String> oldList = Arrays.asList(StrUtil.split(target.getRelatedTargetIds(), ","));
		List<String> newList = Arrays.asList(StrUtil.split(newRelatedTargetIds, ","));

		//更新当前指标关联信息
		target.setRelatedTargetIds(newRelatedTargetIds);
		target.setRelatedTargetNames(getNamesByIds(newRelatedTargetIds));
		log.info(StrUtil.format("更新当前指标【{}】，新ids:【{}】", target.getName(), newRelatedTargetIds));
		target = save(target);

		//本次新去除的指标（这些指标也要对应【删除】本次操作的指标的关联）
		List<String> removeList = CollUtil.filterNew(oldList, s -> !CollUtil.contains(newList, s));
		for(String id : removeList){
			Target target1 = get(id);
			if(target1 == null) continue;

			List<String> idList = CollUtil.newArrayList(StrUtil.split(target1.getRelatedTargetIds(), ","));
			if(CollUtil.contains(idList, keyId)){
				String ids = StrUtil.join(",", CollUtil.removeAny(idList, keyId));
				target1.setRelatedTargetIds(ids);
				target1.setRelatedTargetNames(getNamesByIds(ids));
				log.info(StrUtil.format("--- 更新去除的指标【{}】，新ids:【{}】", target1.getName(), ids));
				save(target1);
			}
		}

		//本次新添加的指标（这些指标也要对应【增加】本次操作的指标的关联）
		List<String> addList = CollUtil.filterNew(newList, s -> !CollUtil.contains(oldList, s));
		for(String id : addList){
			Target target1 = get(id);
			if(target1 == null) continue;
			List<String> idList = CollUtil.newArrayList(StrUtil.split(target1.getRelatedTargetIds(), ","));
			if(!CollUtil.contains(idList, keyId)){
				String ids = StrUtil.join(",", CollUtil.addAll(idList, keyId));
				target1.setRelatedTargetIds(ids);
				target1.setRelatedTargetNames(getNamesByIds(ids));
				log.info(StrUtil.format("+++ 更新增加的指标【{}】，新ids:【{}】", target1.getName(), ids));
				save(target1);
			}
		}

	}

	@Async
	@Override
	public void addReadCount(Target target) {
		if(target != null){
			target.setReadCount((target.getReadCount()!=null ? target.getReadCount() : 0) + 1);
			save(target);
		}
	}

	@Override
	public int getTargetLabelCount() {
		List<String> labelList = targetDao.findAllTargetLabel();
		String s = StrUtil.join("&", labelList);
		String[] l = StrUtil.split(s, "&");
		return l.length;
	}

	@Override
	public void updateParentTarget(Target target, String newParentTargetId) {
		if(target == null || ObjectUtil.equal(FlowEnum.ProcessState.Draft, target.getProcessState())) return;
		if(StrUtil.equals(target.getParentTargetId(), newParentTargetId)) return;
		Target parent = get(newParentTargetId);
		if(parent == null) return;
		String parentPath = StrUtil.isBlank(parent.getPath()) ? newParentTargetId : parent.getPath();

		//1.先更新自己的父级和路径
		if(StrUtil.isBlank(newParentTargetId)){
			target.setParentTargetId(null);
			target.setPath(target.getId());
		}else{
			target.setParentTargetId(parent.getId());
			target.setPath(parentPath + "," + target.getId());
			target.setTargetClassDict(parent.getTargetClassDict());
		}
		save(target);

		//2.更新自己下面的子级的路径
		List<Target> list = findAll(SpecificationFactory.eq("parentTargetId", target.getId()));
		list.forEach(t -> {
			t.setPath(target.getPath() + "," + target.getId());
			t.setTargetClassDict(target.getTargetClassDict());
			save(t);
		});
	}

	@Override
	public List<String> findAllSonList(String targetId) {
		List<String> list = findSon(targetId);
		list.forEach(System.out::println);
		return list;
	}

	//递归查询自己下面所有的子项目
	private List<String> findSon(String targetId){
		List<String> targetList = new ArrayList<>();
		List<Target> list = findAll(SpecificationFactory.eq("parentTargetId", targetId));
		if(list.size() > 0){
			list.forEach(t -> {
				targetList.add(t.getId());
				targetList.addAll(this.findSon(t.getId()));
			});
		}

		return targetList;
	}

	@Override
	public List<Map<String, String>> getTree() {
		List<Map<String, String>> list = new ArrayList<>();

		List<Dict> dictList = dictService.findDictList(DictEnum.target_class);
		dictList.forEach(d -> {
			Map<String, String> map = new HashMap<>();
			map.put("id", d.getId());
			map.put("name", StrUtil.format("<span class='ztreeTargetItem ztreeTargetTitle'>{}</span>", d.getName()));
			map.put("open", "true");
			map.put("pId", "0");
			list.add(map);
		});


		List<Rule> rules = new ArrayList<>();
		rules.add(Rule.eq("state", BaseEnumManager.StateEnum.Enable));
		rules.add(Rule.eq("processState", FlowEnum.ProcessState.Finished));
		List<Target> targetList = findAll(SpecificationFactory.where(rules));
		targetList.forEach(t -> {
			Dict dict = t.getTargetClassDict();
			Map<String, String> map = new HashMap<>();
			String starHtml = "";
			if(ObjectUtil.equal(1, t.getLevel())) starHtml = "★★★";
			if(ObjectUtil.equal(2, t.getLevel())) starHtml = "★★";
			if(ObjectUtil.equal(3, t.getLevel())) starHtml = "★";
			String name = StrUtil.format("<span class='ztreeTargetItem'>{}</span><span class='ztreeTargetStar'> {}</span>", t.getName(), starHtml);

			map.put("id", t.getId());
			map.put("name", name);
			map.put("open", "true");
			map.put("pId", StrUtil.blankToDefault(t.getParentTargetId(), dict!=null ? dict.getId() : "0"));
			list.add(map);
		});
		return list;
	}

	@Override
	public List<Map<String, String>> getTreeByTargetClass(String targetClassId) {
		List<Map<String, String>> list = new ArrayList<>();
		if(StrUtil.isBlank(targetClassId)) return list;
		List<Rule> rules = new ArrayList<>();
		rules.add(Rule.eq("state", BaseEnumManager.StateEnum.Enable));
		rules.add(Rule.eq("processState", FlowEnum.ProcessState.Finished));
		rules.add(Rule.notNull("targetClassDict"));
		rules.add(Rule.eq("targetClassDict.id", targetClassId));
		List<Target> targetList = findAll(SpecificationFactory.where(rules));
		targetList.forEach(t -> {
			Map<String, String> map = new HashMap<>();
			String starHtml = "";
			if(ObjectUtil.equal(1, t.getLevel())) starHtml = "★★★";
			if(ObjectUtil.equal(2, t.getLevel())) starHtml = "★★";
			if(ObjectUtil.equal(3, t.getLevel())) starHtml = "★";
			String name = StrUtil.format("<span class='ztreeTargetItem'>{}</span><span class='ztreeTargetStar'> {}</span>", t.getName(), starHtml);

			map.put("id", t.getId());
			map.put("name", name);
			map.put("open", "true");
			map.put("pId", StrUtil.blankToDefault(t.getParentTargetId(), "0"));
			list.add(map);
		});
		return list;
	}
}
